package gaileenchess;

import java.util.LinkedList;

abstract public class Piece
{
    public enum Type {BISHOP, KING, KNIGHT, PAWN, QUEEN, ROOK};
    
    public final Common.Side side; // the colour of the current piece
    public final Type type;
    private int row;
    private int column;

    private boolean hasMoved=false;
    
    
    public Piece(Common.Side s, Type t, int r, int c)
    {
        this.side = s;
        this.type = t;
        this.row = r;
        this.column = c;
    }
    
    // return the enum identifying the type of the current piece
    public Type getType()
    {
        return this.type;
    }
    
    // return the letter identifying the type of the current piece
    public String getStringType()
    {
        switch(this.type)
        {
            case BISHOP:
            return "B";
            case KING:
            return "K";
            case KNIGHT:
            return "N";
            case PAWN:
            return "P";
            case QUEEN:
            return "Q";
            case ROOK:
            return "R";
        }
        return "";
    }
    
    // return an enum corresponding to which colour the piece is
    public Common.Side getSide()
    {
        return this.side;
    }
    
    // return a string corresponding to which colour the piece is
    public String getStringSide()
    {
        if(this.side == Common.Side.WHITE)
        {
            return "W";
        }
        
        return "B";
    }
    
    public int getRow()
    {
        return this.row;
    }
    
    public int getCol()
    {
        return this.column;
    }
    
    public void move(Board.Position pos, boolean countMove)
    {
        this.row = pos.row;
        this.column = pos.column;
        
        if(countMove)
        {
            hasMoved=true;
        }
    }
    
    public Board.Position getPosition()
    {
        return new Board.Position(getRow(), getCol());
    }
    
    // determine, from the individual piece's point of view, if the given move is valid
    abstract public boolean isValidMove(Common.Side playerSide, Board board, Board.Position pos1, Board.Position pos2);

    public boolean hasMoved()
    {
        return hasMoved;
    }
    
    // has no return value, but will add to passed in list of moves (and should ONLY add, not modify)
    abstract public void getValidMoves(Common.Side playerSide, Board board, LinkedList<Board.Position.Move> pieces, boolean check, int player);
    //TODO: castling?
    
    protected void getValidMovesHelper(Common.Side playerSide, Board board, LinkedList<Board.Position.Move> pieces, Board.Position direction, int limit, boolean check, int player)
    {
        boolean keepGoing = true;
        Board.Position move = getPosition();
        int count = 0;
        
        while(keepGoing && (count < limit || limit == 0))
        {
            move = move.add(direction);
            
            keepGoing = move.isValid() && getValidMovesCheckAndAdd(playerSide, board, pieces, move, check, player);
            
            count++;
        }
    }
    
    protected boolean getValidMovesCheckAndAdd(Common.Side playerSide, Board board, LinkedList<Board.Position.Move> pieces, Board.Position move, boolean check, int player)
    {
        Board.Position currentPos = getPosition();
        
        if(move.isValid() && !board.isOccupied(move, playerSide))
        {
            if(!board.willBeInCheck(player, currentPos, move))//if(!check || (check && !board.willBeInCheck(player, currentPos, move)))
            {
                pieces.addFirst(new Board.Position.Move(currentPos, move));
                /*
                TODO
                stalemate test:
                BK ** ** ** ** ** ** **
                ** ** ** WQ ** ** ** **
                ** ** ** ** ** ** ** **
                ** ** WQ ** ** ** ** **
                ** ** ** ** ** ** ** **
                ** ** ** ** ** ** ** **
                ** ** ** ** ** ** ** **
                ** ** ** ** ** ** ** WK
                */
            }
            
            if(board.isOccupied(move))
            {
                return false;
            }
            
            return true;
        }
        
        return false;
    }
}
